#include "ChatterBoxServer.h"
#include <QTcpSocket>
#include <QRegExp>
#include <QFile>

int hlpT = 10000;
int hlp = 3;

ChatterBoxServer::ChatterBoxServer(QObject *parent) : QTcpServer(parent)
{
    userSrv = new Database(this);
    quizSrv = new QuizMain(this,hlpT,hlp);
    real = true;
}

void ChatterBoxServer::incomingConnection(int socketfd)
{
    QTcpSocket *client = new QTcpSocket(this);
    client->setSocketDescriptor(socketfd);
    clients.insert(client);

    qDebug() << "New client from:" << client->peerAddress().toString();

    connect(client, SIGNAL(readyRead()), this, SLOT(readyRead()));
    connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));
}

void ChatterBoxServer::readyRead()
{
    QTcpSocket *client = (QTcpSocket*)sender();
    while(client->canReadLine())
    {
        QString line = QString::fromUtf8(client->readLine()).trimmed();

        QRegExp meRegex("^/me:(.*)$");
        QRegExp questRegex("^/QUEST:(.*)$");

        if (line == "BAD_QUESTION")
        {
            QFile file("report.txt");
            if (!file.open(QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text))
                return;

            QTextStream out(&file);
            out << "Reported questionID: (" << QString::number(quizSrv->getCurrQuestionID()) << ") " << quizSrv->getCurrQuestion() << " by user: " << users[client] << endl;
            return;
        }

        if(meRegex.indexIn(line) != -1)
        {
            QString user = meRegex.cap(1);
            if (!userNotExist(user) || user.isEmpty())
            {
                real = false;
                client->abort();
                return;
            }
            users[client] = user;
            foreach(QTcpSocket *client, clients)
                client->write(QString("Server:" + user + " has joined.\n").toUtf8());
            sendUserList();
            client->write(QString("/settings:" + QString::number(hlpT/1000) + " * " + QString::number(hlp) + "\n").toUtf8());
            quizSrv->displayCurrQuestion();
        }
        else if(questRegex.indexIn(line) != -1)
        {
            QStringList question = questRegex.cap(1).split('*');
            //qDebug() << line << " ||| " << question[0] << " " << question[1];
            if (question.size() == 2)
                quizSrv->addQuestion(question[0], question[1]);
            return;

        }
        else if(users.contains(client))
        {
            QString message = line;
            QString user = users[client];
            //qDebug() << "User:" << user;
            //qDebug() << "Message:" << message;
            if (message == "!rank")
                userSrv->showScore(user);
            if (message == "!top3")
                userSrv->showTop3();
            if (quizSrv->checkAnswer(user, message))
                quizSrv->rewardUser(user);


            foreach(QTcpSocket *otherClient, clients)
                otherClient->write(QString(user + ":" + message + "\n").toUtf8());
        }
        else
        {
            qWarning() << "Got bad message from client:" << client->peerAddress().toString() << line;
        }
    }
}

void ChatterBoxServer::disconnected()
{
    QTcpSocket *client = (QTcpSocket*)sender();
    QString reason;
    if (real)
        reason = "Normal DC";
    else
        reason = "Already connected DC";

    qDebug() << "Client disconnected: " << client->peerAddress().toString() << " Reason: " << reason;

    clients.remove(client);

    QString user = users[client];
    users.remove(client);

    sendUserList();
    if (real)
        foreach(QTcpSocket *client, clients)
            client->write(QString("Server:" + user + " has left.\n").toUtf8());
    real = true;
}

void ChatterBoxServer::sendUserList()
{
    QStringList userList;
    foreach(QString user, users.values())
        userList << user + ":" + QString::number(userSrv->getScore(user)) + ":" + QString::number(userSrv->getRank(user));

    foreach(QTcpSocket *client, clients)
        client->write(QString("/users:" + userList.join(",") + "\n").toUtf8());
}

void ChatterBoxServer::sendText(QString text)
{
    foreach(QTcpSocket *otherClient, clients)
        otherClient->write(QString("QuizMaster: " + text + "\n").toUtf8());
}

bool ChatterBoxServer::userNotExist(QString name)
{
    QMap<QTcpSocket*,QString>::const_iterator i = users.constBegin();
    while (i != users.constEnd()) {
        if (i.value().toLower() == name.toLower())
        {
            //qDebug() << "User exist";
            return false;
        }
        ++i;
    }
    //qDebug() << "User not exist";
    return true;
}

void ChatterBoxServer::sendQuestion(int nr, QString question)
{
    foreach(QTcpSocket *client, clients)
        client->write(QString("/question:" + QString::number(nr) + "*" + question + "\n").toUtf8());
}

void ChatterBoxServer::sendHint(QString hint, int count, bool fullanswer)
{
    if (fullanswer)
        count = -1;

    foreach(QTcpSocket *client, clients)
        client->write(QString("/hint:" + hint + "|" + QString::number(count) + "\n").toUtf8());
}

Database* ChatterBoxServer::getUserSrv()
{
    return userSrv;
}
